#ifndef SERVEROPERATION_H
#define SERVEROPERATION_H

#include <QObject>
#include <QRunnable>
#include "tcpserver.h"
#include "requestcodec.h"
#include "rsacrypto.h"
#include "seckeyshm.h"
#include "dboperation.h"
#include "respondcodec.h"

// 在这个头文件中声明几个类(最起码是两个)
//////////////////////////////////////////////
/////////////   处理客户端的新连接  /////////////
//////////////////////////////////////////////
/// 这是一个要添加到线程池中的任务类
class AcceptConn : public QObject, public QRunnable
{
    Q_OBJECT
public:
    AcceptConn();
    ~AcceptConn();

    void run();
    void stop();    // 终止run()中的事件循环

signals:
    void sendMsg(QString msg);

private:
    TcpServer* m_server;
    SeckeyShm* m_shm;   // 共享内存
    bool m_stop = false;
};



//////////////////////////////////////////////
/////////////   和客户端通信的类    /////////////
//////////////////////////////////////////////
/// 这是一个要添加到线程池中的任务类
/// 这个类中需要一个套接字通信的对象, 并且这个类的实例在建立新连接之后创建
class Communication : public QObject, public QRunnable
{
    Q_OBJECT
public:
    enum CmdType{Consult, Verify, Logout, Login};
    enum KeyLen{
        L16 = 16, L24=24, L32=32
    };
    Communication(TcpSocket* tcp, SeckeyShm* shm);
    ~Communication();

    // 秘钥协商
    void seckeyConsult(RequestInfo* reqMsg);

    // 秘钥校验
    void seckeyVerify(RequestInfo* reqMsg);

    // 秘钥注销
    void seckeyLogout(RequestInfo* reqMsg);

    // 客户端登录
    void clientLogin(RequestInfo* reqMsg);

    void run();

signals:
    void sendMsg(QString msg);

private:
    // 校验客户端身份和数据
    bool identifyVerify(RsaCrypto &rsa, RequestInfo* reqMsg);
    // 对称加密使用的aes, 秘钥长度: 16, 24, 32 字节
    QString generateAesKey(KeyLen len);
    // 发送序列化的数据
    void sendSerializeMsg(RespondInfo* info, QString log);

private:
    TcpSocket* m_tcp;   // 保存构造函数的参数, 可以用于通信的套接字对象的地址
    SeckeyShm* m_shm;   // 共享内存
    DBOperation* m_db;  // 数据库操作对象
};

#endif // SERVEROPERATION_H
